# — coding: utf-8 –
import os
import re
import subprocess
import sys
import time
import traceback
from time import sleep
import uiautomator2 as u2
import pandas as pd
from xml.etree import ElementTree as ET, ElementTree
import logging

from uiautomator2 import UiObject

import Config
from Config import Params
from Decorators.CommonDecorator2 import TryExcept, RetryIfIs
from Service.MyLogger import MyLogger
from Service.U2Syner import U2Syner
from Utils import IOUtil, TimeUtil, DirUtil, ConvertUtil, RecordUtil

logFileName = os.path.basename(__file__).split(".")[0]
log = MyLogger(r"./Logs/%s.log" % (logFileName), logging.DEBUG, logging.DEBUG)

from threading import Thread, current_thread

ifNotFoundWaitSeconds = 10
threadDict={}
deviceSerial = ''

def executeADB(adbStr: str, d: u2.Device):
    # 返回一个命令的数据流 output为requests.models.Response
    output = d.shell(adbStr, stream=True)
    try:
        # 按行读取，iter_lines为迭代响应数据，一次一行
        for line in output.iter_lines():
            print(line.decode('utf8'))
    finally:
        output.close()


fbFakeEditId = "com.unnoo.quan:id/fbFakeEdit"
mRecyclerViewId = "com.unnoo.quan:id/mRecyclerView"
userNameViewId = "com.unnoo.quan:id/userNameView"
answerTextViewId = "com.unnoo.quan:id/answerTextView"
tvLikesCountId = "com.unnoo.quan:id/tvLikesCount"
tvCommentCountId = "com.unnoo.quan:id/tvCommentCount"
shareBtnId = "com.unnoo.quan:id/shareBtn"
flexShareId = "com.unnoo.quan:id/flexShare"
userNameArr = []
pkgNameTool = "com.codeboy.qianghongbao"
pkgNameXHS = "com.xingin.xhs"
fbFakeEditBounds = []


def findWithScrolling(d: u2.Device, resourceId=None):
    res = None
    while True:
        if resourceId is not None:
            res = d(resourceId=resourceId)
        if res is not None and res.exists:
            print("yzprt res.get_text af scroll:", res.get_text())
            return res
        else:
            scrollALittle(d)

def getTextStrByTvs(tvs,sep='\t'):
    textArr = []
    for i in range(len(tvs)):
        textArr.append(tvs[i].get_text())
    return sep.join(textArr)
def walkXQ(d: u2.Device = None):
    if d is None:
        uu = U2Syner()
        d: u2.Device = uu.deviceList[0]
    d.watcher.when("我知道了").click()
    d.watcher.start()
    appInfo = d.app_current()
    print("yzprt appInfo:", type(appInfo), appInfo)
    TIMEOUT_DEFAULT = 5.0
    MAX_SCROLL_COUNT = 500
    scrollCount = 0
    vpScroll = d(resourceId="com.xueqiu.android:id/view_pager")
    isConcern = False
    while scrollCount < MAX_SCROLL_COUNT:
        # tvUserName = d(resourceId="com.xueqiu.android:id/userName")
        tvUserName = findWithScrolling(d, resourceId="com.xueqiu.android:id/userName")
        tvUserNameBounds = tvUserName.bounds()
        userName = tvUserName.get_text()
        if (tvUserName is not None) and (userName not in userNameArr):
            tvCreatedAt = d(resourceId="com.xueqiu.android:id/created_at")
            while True:
                tvStatusText = findWithScrolling(d, resourceId="com.xueqiu.android:id/statusText")
                if tvStatusText.bounds()[-1]>tvUserNameBounds[-1]:
                    print(f'yzprt 找到了对应的tvStatusText..........................')
                    break
                else:
                    tvUserName = findWithScrolling(d, resourceId="com.xueqiu.android:id/userName")
                    tvUserNameBounds = tvUserName.bounds()
                scrollALittle(d)
            textStatusText = tvStatusText.get_text().replace("\n", "@n#")
            tvTitle = tvStatusText.sibling(resourceId="com.xueqiu.android:id/tv_title")
            if tvTitle.exists:
                textTitle = tvTitle.get_text()
            else:
                textTitle = None
            # tvTitles = d(resourceId="com.xueqiu.android:id/tv_title")
            # tvTitle = tvTitles[0]
            # for i in range(len(tvTitles)):
            #     tvTitle = tvTitles[i]
            #     tvContentSib = tvTitle.sibling(resourceId="com.xueqiu.android:id/statusText")
            #     if tvContentSib.exists:
            #         break
            # textTitle = tvTitle.get_text()
            print(f'yzprt textTitle:{textTitle}, textStatusText:{textStatusText}')
            with open(os.path.join(os.path.join(Config.Params.ROOT_DIR,"./raw/records"), f"xq_articles_{d.serial}.txt"), 'a', encoding='utf-8',
                      errors='ignore') as f:
                f.write(f'\n{textTitle}\t{userName}\t{tvCreatedAt.get_text()}\t{textStatusText}')
            if isConcern:
                tvConcern = d(resourceId="com.xueqiu.android:id/tv_text")
                tvConcern.click()
            tvUserName.click()
            d(resourceId="com.xueqiu.android:id/user_info_detail").wait(timeout=TIMEOUT_DEFAULT)
            tvUserInfoDetail = d(resourceId="com.xueqiu.android:id/user_info_detail")
            tvCounts = d(resourceId="com.xueqiu.android:id/tv_count")
            textCounts = getTextStrByTvs(tvCounts)
            tvSubTitles = d(resourceId="com.xueqiu.android:id/tv_sub_title")
            textSubTitles = getTextStrByTvs(tvSubTitles)
            tvCertificationDescs = d(resourceId="com.xueqiu.android:id/certification_desc")
            textCertificationDescs = getTextStrByTvs(tvCertificationDescs,sep="@t#")
            print(f'yzprt textCounts:{textCounts}, textSubTitles:{textSubTitles}, textCertificationDescs:{textCertificationDescs}')
            tvUserInfoDetail.click()
            d(resourceId="com.xueqiu.android:id/user_id").wait(timeout=TIMEOUT_DEFAULT)
            tvUserId = d(resourceId="com.xueqiu.android:id/user_id")
            tvBrief = d(resourceId="com.xueqiu.android:id/user_description")
            textBrief = tvBrief.get_text() if tvBrief.exists else None
            tvUserGender = d(resourceId="com.xueqiu.android:id/user_gender")
            textUserGender = tvUserGender.get_text() if tvUserGender.exists else None
            tvUserArea = d(resourceId="com.xueqiu.android:id/user_area")
            textUserArea = tvUserArea.get_text() if tvUserArea.exists else None
            tvIP = d(resourceId="com.xueqiu.android:id/tv_ip")
            textIP = tvIP.get_text() if tvIP.exists else None
            tvRealNameVerifiedTag = d(resourceId="com.xueqiu.android:id/real_name_verified_tag")
            textRealNameVerifiedTag = tvRealNameVerifiedTag.get_text() if tvRealNameVerifiedTag.exists else None
            # tvHornorDesc = d(resourceId="com.xueqiu.android:id/honor_desc")
            # tvVerifiedDesc = d(resourceId="com.xueqiu.android:id/verified_description")
            print(f'yzprt tvUserId:{tvUserId.get_text()}, tvUserGender:{textUserGender}, tvUserArea:{textUserArea}, '
                  f'tvIP:{textIP}, tvRealNameVerifiedTag:{textRealNameVerifiedTag}, textBrief:{textBrief}')
            with open(os.path.join(os.path.join(Config.Params.ROOT_DIR,"./raw/records"), f"xq_users_{d.serial}.txt"), 'a', encoding='utf-8',errors='ignore') as f:
                f.write(f'\n{userName}\t{tvUserId.get_text()}\t{textCounts}\t{textSubTitles}\t{textUserArea}\t{textIP}'
                        f'\t{textUserGender}\t{textRealNameVerifiedTag}\t{textCertificationDescs}\t{textBrief}')
            d.press("back")
            sleep(1)
            ivMessege = d(resourceId="com.xueqiu.android:id/dm")
            ivMessege.click()
            d(resourceId="com.xueqiu.android:id/input").wait(timeout=TIMEOUT_DEFAULT)
            etMessegeInput = d(resourceId="com.xueqiu.android:id/input")
            sendContent = "你好,看了你的分享,感觉很不错,能加个好友吗?"
            etMessegeInput.set_text(sendContent)
            # ivMessegeSend = d(resourceId="com.xueqiu.android:id/send")
            # ivMessegeSend.click()
            print(f'yzprt 假装已按下了发送按钮, 发送了:{sendContent}')
            sleep(2)
            d.press("back")
            sleep(0.5)
            d.press("back")
            sleep(0.5)
            while not d(resourceId="com.xueqiu.android:id/home_search").exists:
                print(f'yzprt home_search not exists...')
                d.press("back")
                sleep(2)
            rlHomeSearch = d(resourceId="com.xueqiu.android:id/home_search")
            if rlHomeSearch.exists:
                while True:
                    tvLikesCount = d(resourceId="com.xueqiu.android:id/reward_snowcoin")
                    if tvLikesCount.exists:
                        print("yzprt tvLikesCount.exists:", tvLikesCount.exists)
                        if tvLikesCount.bounds()[-1] > tvUserNameBounds[-1]:
                            print(f'yzprt break.....................................')
                            print("yzprt tvLikesCount.bounds()[-1]:", tvLikesCount.bounds()[-1])
                            print("yzprt tvUserNameBounds[-1]:", tvUserNameBounds[-1])
                            break
                            # if tvLikesCount.bounds()[-1] + 2 < fbFakeEditBounds[1] or tvLikesCount.bounds()[1] > \
                            #         fbFakeEditBounds[-1] + 2:
                            #     print("yzprt tvLikesCount.bounds()[-1]+2:", tvLikesCount.bounds()[-1] + 2)
                            #     print("yzprt fbFakeEditBounds[1]:", fbFakeEditBounds[1])
                            #     print("yzprt tvLikesCount.bounds()[1]:", tvLikesCount.bounds()[1])
                            #     print("yzprt fbFakeEditBounds[-1]+2:", fbFakeEditBounds[-1] + 2)
                            #     break
                        else:
                            tvUserName = d(text=userName)
                            if tvUserName.exists:
                                tvUserNameBounds = tvUserName.bounds()
                                userName = tvUserName.get_text()
                            else:
                                tvUserNameBounds = [-99, -99, -99, -99]
                            print("yzprt else...")
                            print("yzprt tvLikesCount.bounds()[-1]:", tvLikesCount.bounds()[-1])
                            print("yzprt tvUserNameBounds[-1]:", tvUserNameBounds[-1])
                    scrollALittle(d)
                tvRetweetCount = d(resourceId="com.xueqiu.android:id/retweet_count")
                tvCommentCount = d(resourceId="com.xueqiu.android:id/comment_count")
                likesCount = ConvertUtil.numStr2numInt(tvLikesCount.get_text())
                retweetCount = ConvertUtil.numStr2numInt(tvRetweetCount.get_text())
                commentCount = ConvertUtil.numStr2numInt(tvCommentCount.get_text())
                print(f'yzprt likesCount:{likesCount}, retweetCount:{retweetCount}, commentCount:{commentCount}')
                with open(os.path.join(os.path.join(Config.Params.ROOT_DIR,"./raw/records"), f"xq_articles_{d.serial}.txt"), 'a', encoding='utf-8',errors='ignore') as f:
                    f.write(f'\t{likesCount}\t{commentCount}\t{retweetCount}')
                userNameArr.append(userName)
                scrollCount += 1
        scrollALittle(d)
        # vpScroll.scroll(steps=100)


    d.watcher.stop()
    d.watcher.remove()


def walkZSXQ():
    uu = U2Syner()
    d: u2.Device = uu.deviceList[0]
    fbFakeEdit = d(resourceId=fbFakeEditId)
    fbFakeEditBounds = fbFakeEdit.bounds()
    # d.toast.show("Hello world 00")
    d.watcher.when("打开辅助服务").press("back")
    d.watcher.start()
    # uu.dumpHierarchy(d)
    appInfo = d.app_current()
    print("yzprt appInfo:", type(appInfo), appInfo)
    while True:
        # 下面这行是报错行: uiautomator2.exceptions.UiObjectNotFoundError: -32001 Jsonrpc error:
        # <androidx.test.uiautomator.UiObjectNotFoundException> data: UiSelector[RESOURCE_ID=com.unnoo.quan:id/userNameView], method: getText
        tvUserName = findWithScrolling(d, resourceId=userNameViewId)
        tvUserNameBounds = tvUserName.bounds()
        userName = tvUserName.get_text()
        bidderTime = d(resourceId="com.unnoo.quan:id/timeView").get_text()
        if (tvUserName is not None) and (userName not in userNameArr):
            while True:
                tvLikesCount = d(resourceId=tvLikesCountId)
                if tvLikesCount.exists:
                    print("yzprt tvLikesCount.exists:", tvLikesCount.exists)
                    if tvLikesCount.bounds()[-1] > tvUserNameBounds[-1]:
                        print("yzprt tvLikesCount.bounds()[-1]:", tvLikesCount.bounds()[-1])
                        print("yzprt tvUserNameBounds[-1]:", tvUserNameBounds[-1])
                        if tvLikesCount.bounds()[-1] + 2 < fbFakeEditBounds[1] or tvLikesCount.bounds()[1] > \
                                fbFakeEditBounds[-1] + 2:
                            print("yzprt tvLikesCount.bounds()[-1]+2:", tvLikesCount.bounds()[-1] + 2)
                            print("yzprt fbFakeEditBounds[1]:", fbFakeEditBounds[1])
                            print("yzprt tvLikesCount.bounds()[1]:", tvLikesCount.bounds()[1])
                            print("yzprt fbFakeEditBounds[-1]+2:", fbFakeEditBounds[-1] + 2)
                            break
                    else:
                        tvUserName = d(text=userName)
                        if tvUserName.exists:
                            tvUserNameBounds = tvUserName.bounds()
                            userName = tvUserName.get_text()
                            bidderTime = d(resourceId="com.unnoo.quan:id/timeView").get_text()
                        else:
                            tvUserNameBounds = [-99, -99, -99, -99]
                        print("yzprt else...")
                        print("yzprt tvLikesCount.bounds()[-1]:", tvLikesCount.bounds()[-1])
                        print("yzprt tvUserNameBounds[-1]:", tvUserNameBounds[-1])
                scrollALittle(d)
            tvCommentCount = d(resourceId=tvCommentCountId)
            tvAnswer = d(resourceId=answerTextViewId)
            try:
                likesCount = int(tvLikesCount.get_text())
            except:
                likesCount = 0
                log.info("yzlog likesCount abnormal:", likesCount)
            try:
                commentCount = int(tvCommentCount.get_text())
            except:
                commentCount = 0
                log.info("yzlog commentCount abnormal:", commentCount)
            try:
                answerText = tvAnswer.get_text()
            except:
                answerText = ""
                log.info("yzlog answerText abnormal:", answerText)
            print("yzprt likesCount,commentCount,answerText:", likesCount, commentCount,
                  answerText.replace("\n", "@n#"))
            d(resourceId=shareBtnId).click()
            llFlexShare = d(resourceId=flexShareId)
            llFlexShare.scroll.horiz.toEnd()
            d(text="复制链接").click()
            d.app_start(pkgNameTool, wait=True)
            # d.set_clipboard(TimeUtil.getFormatTimeNow())
            d(text="测试按钮").click()
            link = d(resourceId="com.codeboy.qianghongbao:id/et_msg").get_text()
            with open(os.path.join(os.path.join(Config.Params.ROOT_DIR,"./raw/records"), "zsxq_bidders.txt"), 'a', encoding='utf-8',
                      errors='ignore') as f:
                f.write("\n%s\t%s\t%s\t%s\t%s\t%s" % (
                userName, bidderTime, likesCount, commentCount, link, answerText.replace("\n", "@n#")))

            d.app_start(appInfo["package"], wait=True)
            userNameArr.append(userName)
            print("yzprt userNameArr:", userNameArr)
        # d(resourceId=mRecyclerViewId).scroll.to(resourceId=userNameViewId)
        d(resourceId=mRecyclerViewId).scroll(steps=100)
        # d.toast.show("Hello world")
    d.watcher.stop()
    d.watcher.remove()


def clickOuter(d: u2.Device):
    d.click(0.5, 0.98)


def scrollALittle(d: u2.Device):
    d.swipe(400, 650+200, 400, 380+200)
    print("yzprt scrollALittle...")


def isNewTvTextList(tvList: list, oldTvTextList: list):
    for i in range(len(tvList)):
        if tvList[i].get_text() in oldTvTextList:
            print("yzprt old view:", tvList[i].get_text(), oldTvTextList)
            return False
    for i in range(len(tvList)):
        print(f"yzprt new view tvList[{i}].get_text():", tvList[i].get_text())
    print("yzprt new view:", oldTvTextList)
    return True


def getUserMsgByDumpHi(d: u2.Device):
    maxCollectCount = 2
    collectCount = 0
    lastNCount = 3
    resIdDict = {}
    userMsgList = []
    while collectCount < maxCollectCount:
        xmlContent = d.dump_hierarchy()
        root = ET.fromstring(xmlContent)
        # # 获xml文件的内容取根标签
        # root = tree.getroot()
        print(root)
        rvNodeList = root.findall('.//node[@class="androidx.recyclerview.widget.RecyclerView"]')
        print("yzprt rvNodeList:", rvNodeList)
        tvNodeList = rvNodeList[0].findall('.//node[@class="android.widget.TextView"]')
        print("yzprt len(resList):", len(tvNodeList))
        if len(tvNodeList)<=0:
            raise Exception
        for i in range(len(tvNodeList)):
            ee = tvNodeList[i]
            # textInfoDict = {"text":ee.attrib['text'],"resource-id":ee.attrib['resource-id'],"class":ee.attrib['class'],"bounds":ee.attrib['bounds']}
            textInfoDict = {"text": ee.attrib['text'], "resource-id": ee.attrib['resource-id']}
            text = textInfoDict['text']
            resId = textInfoDict['resource-id']
            if re.search(r"^\d+$", text):
                textType = "likesCount"
            elif re.search(r" \d\d-\d\d ", text) or re.search(r"[天时]前 $", text):
                textType = "message"
            elif text == "作者" or text == "关注" or text == "作者赞过" or text.find("条评论") >= 0 or text.find(
                    "条回复") >= 0 or text.find("快来评论") >= 0 or text.find("置顶评论") >= 0:
                textType = "otherType"
            elif len(text) < 15 and text.find(" ") < 0 and not re.search(r"^\d", text):
                textType = "userName"
            else:
                textType = "unknownType"
            # 逐渐生成resIdDict以在后续获取目标控件的resourId:
            # if textType in ["userName", "likesCount", "message"]:
            #     try:
            #         resIdDict[textType][resId] += 1
            #     except:
            #         if textType not in resIdDict:
            #             resIdDict[textType] = {}
            #         resIdDict[textType][resId] = 1
            # 采集列表信息并整理:
            if textType in ["userName", "message", "likesCount"]:
                print("yzprt resList[%s]:" % (i), i, textType, textInfoDict)
                if textType == "userName":
                    userMsgList.append(text)
                else:
                    userMsgList[-1] += "\t" + text
        print("yzprt userMsgList:", userMsgList)
        if len(userMsgList) >0 and len(userMsgList[-1].split('\t')) < 2:
            userMsgList[-1] = userMsgList[-1].replace('\t', '\t\t')
        # scroll until last tv gone:
        lastNText = []
        lastNTv = []
        for i in range(lastNCount):
            tmpLastText = tvNodeList[-1 - i].attrib['text']
            log.info("yzlog tmpLastText:", tmpLastText)
            lastNText.append(tmpLastText)
            print("yzprt lastNText[%s]:" % (i), tmpLastText)
            lastNTv.append(d(text=tmpLastText)[-1])
        recyclerView = d(className="androidx.recyclerview.widget.RecyclerView")
        while True:
            # recyclerView.swipe("up", steps=15)
            scrollALittle(d)
            isHas1Exists = False
            isHas1Gone = False
            for i in range(lastNCount):
                if lastNTv[i].exists:
                    pass
                    # isHas1Exists = True
                    # print("yzprt %s still exists..." % (lastNText[i]))
                    # break
                else:
                    isHas1Gone = True
                    print("yzprt %s has gone..." % (lastNText[i]))
            if isHas1Gone: # not isHas1Exists:
                break
        # with open(os.path.join(os.path.join(Config.Params.ROOT_DIR, "./raw/records"), "xhs_comments_%s.txt"%(d.serial)), 'a',encoding='utf-8', errors='ignore') as f:
        #     f.write("\n%s" % (text))
        collectCount += 1
        print("yzprt scroll over...", collectCount)

    with open(os.path.join(os.path.join(Config.Params.ROOT_DIR,"./raw/records"), "xhs_comments_%s.txt"%(d.serial)), 'a', encoding='utf-8', errors='ignore') as f:
        f.write("\n%s" % ('\n'.join(userMsgList)))
    # 通过resIdDict获取目标控件的resourId:
    # print("yzprt resIdDict:", resIdDict)
    # viewIdDict = {}
    # for k, v in resIdDict.items():
    #     # print("yzprt k,v:", k,v)
    #     maxCount = 0
    #     maxViewId = ""
    #     for kk, vv in v.items():
    #         if vv > maxCount:
    #             maxCount = vv
    #             maxViewId = kk
    #     viewIdDict[k] = maxViewId
    # print("yzprt viewIdDict:", viewIdDict)
    return None


def tsetSth(d:u2.Device=None):
    if d is None:
        uu = U2Syner()
        d: u2.Device = uu.deviceList[0]
    d.watcher.when("打开辅助服务").press("back")
    d.watcher.when("立即安装").press("back")
    d.watcher.when("立即查看").click()
    d.watcher.start()
    appInfo = d.app_current()
    resHi = uu.oDumpHierarchy(d)
    # something: ########################################################################
    # recyclerView = d(className="androidx.recyclerview.widget.RecyclerView")
    # recyclerView.swipe("up")
    pass
    # while True:
    #     scrollALittle(d)
    #     sleep(1)
    # something: ########################################################################
    pass
    # xmlContent = d.dump_hierarchy()
    # root = ET.fromstring(xmlContent)
    # # nodeIvList = root.findall('.//node[@class="android.widget.ImageView"]')
    # nodeIvList = root.findall('.//')
    # for i in range(len(nodeIvList)):
    #     nodeIv = nodeIvList[i]
    #     if nodeIv.attrib['content-desc'].find("¥")>=0:
    #         print("yzprt nodeIv.attrib:", nodeIv.attrib)
    pass
    img = d.screenshot()
    print("yzprt img:", img)
    filePath = os.path.join(Config.Params.ROOT_DIR, r"raw/imgs/" + "ScreenShot_"
                            + TimeUtil.stampS2TimeStr(TimeUtil.getStamp10(), fmt="mdHMS") + ".jpg")
    print("yzprt filePath:", filePath)
    img.save(filePath)
    pass
    while False:
        pass
    d.watcher.stop()
    d.watcher.remove()


def walkXHS_COMMENTS(d:u2.Device=None):
    if d is None:
        uu = U2Syner()
        d: u2.Device = uu.deviceList[0]
    d.watcher.when("打开辅助服务").press("back")
    d.watcher.when("立即安装").press("back")
    d.watcher.when("立即查看").click()
    d.watcher.start()
    appInfo = d.app_current()

    oldTvTextList = []
    # linkList = [
    #     "65 陌年发布了一篇小红书笔记，快来看吧！ 😆 EBE5nFtRkdltTtM 😆 http://xhslink.com/BYHI9s，复制本条信息，打开【小红书】App查看精彩内容！",
    #     # "52 一指风景发布了一篇小红书笔记，快来看吧！ 😆 anBovdx3HSjWhDl 😆 http://xhslink.com/gkEI9s，复制本条信息，打开【小红书】App查看精彩内容！",
    # ]
    linkList = getLinkList(d)
    for i in range(len(linkList)):
        btViewNote = None
        btViewNote = tryClickBtViewNote(d,linkList,ind=i)
        if btViewNote is None:
            log.info("yzlog 没有找到[立即查看]按钮...")
            return
        try:
            d(text="立即查看").click()
        except:
            log.error("yzlog err08112451: 点击[立即查看]失败...", )
        sleep(1)
        xmlContent = d.dump_hierarchy()
        print("yzprt xmlContent:", xmlContent)
        root = ET.fromstring(xmlContent)
        try:
            nodeBottomCommnet = root.findall('.//node[@text="说点什么..."]/../node[@class="android.widget.LinearLayout"]')[-1]
            print("yzprt nodeBottomCommnet.attrib['resource-id']:", nodeBottomCommnet.attrib['resource-id'])
            d(resourceId=nodeBottomCommnet.attrib['resource-id']).click()
        except:
            log.info("yzlog this is not a note:", i,linkList[i])
            continue
            # try:
            #     d(resourceId="com.xingin.xhs:id/commentLayout").click()
            # except:
            #     log.error("yzlog err08112140: 找不到评论的按钮,没法展开评论列表...", )
        # d(className="androidx.recyclerview.widget.RecyclerView").wait(timeout=10)
        # recyclerView = d(className="androidx.recyclerview.widget.RecyclerView")[0]
        getUserMsgByDumpHi(d)

    while True:
        pass
    d.watcher.stop()
    d.watcher.remove()
@RetryIfIs(countDown=3, slpSeconds=2, retryIfIs=None)
def tryClickBtViewNote(d:u2.Device,linkList:list,ind=0):
    # d.set_clipboard(linkList[IOUtil.getOuterIndAndAdd() % len(linkList)])
    d.set_clipboard(linkList[ind])
    d.press("home")
    d.app_start(pkgNameXHS, wait=True)
    sleep(1)
    return d.exists(text="立即查看")
def myPress(d:u2.Device, actStr, count):
    for i in range(count):
        d.press(actStr)
@TryExcept
def xhsLikeCollConcAfBack(d:u2.Device, U:dict, likeRng, collRng, concRng):
    xhsLikeAfBack(d,U,likeRng)
    xhsCollAfBack(d,U,collRng)
    xhsConcAfBack(d,U,concRng)
@TryExcept
def xhsLikeAfBack(d:u2.Device, U:dict, likeRng):
    if ConvertUtil.numStr2numInt(U["点赞数"]) in range(*likeRng):
        d(text=U["点赞数"]).click()
        RecordUtil.recordSthInAct(f"点赞了:: 小红书号:{U['小红书号'].replace('小红书号：', '')}, 昵称:{U['用户昵称']}, 点赞数:{U['点赞数']}, 链接:{U['链接']}",serial=d.serial)
@TryExcept
def xhsCollAfBack(d:u2.Device, U:dict, collRng):
    if ConvertUtil.numStr2numInt(U["收藏数"]) in range(*collRng):
        print(f'yzprt click:收藏')
        d(text=U["收藏数"]).click()
        RecordUtil.recordSthInAct(f"收藏了:: 小红书号:{U['小红书号'].replace('小红书号：', '')}, 昵称:{U['用户昵称']}, 收藏数:{U['收藏数']}, 链接:{U['链接']}",serial=d.serial)
@TryExcept
def xhsConcAfBack(d:u2.Device, U:dict, concRng):
    if ConvertUtil.numStr2numInt(U["关注数"]) in range(*concRng):
        if d(text="已关注").exists:
            log.info(f'yzlog 该作者已关注!')
            return
        print(f'yzprt click:关注')
        d(text="关注").click()
        RecordUtil.recordSthInAct(f"关注了:: 小红书号:{U['小红书号'].replace('小红书号：', '')}, 昵称:{U['用户昵称']}, 关注数:{U['关注数']}, 链接:{U['链接']}",serial=d.serial)
def getHeightOfUio(uio:u2._selector.UiObject):
    return uio.info['bounds']["bottom"]-uio.info['bounds']["top"]
def getWidthOfUio(uio:u2._selector.UiObject):
    return uio.info['bounds']["right"]-uio.info['bounds']["left"]
def getMaxHeightUio(uioList:list):
    maxHeight = -1
    maxInd = -1
    for i in range(len(uioList)):
        uio:u2._selector.UiObject = uioList[i]
        if getHeightOfUio(uio)>maxHeight:
            maxHeight=getHeightOfUio(uio)
            maxInd=i
    return uioList[maxInd]
def getMaxHeightNode(nodeList:list):
    maxHeight = -1
    maxHeightNode = None
    for i in range(len(nodeList)):
        curHeight = getHeight(nodeList[i])
        if curHeight > maxHeight:
            maxHeight = curHeight
            maxHeightNode = nodeList[i]
    return maxHeightNode
def getScrollableNode(nodeList:list):
    scrollableList = []
    for i in range(len(nodeList)):
        if nodeList[i].attrib['scrollable']=='true':
            scrollableList.append(nodeList[i])
    return scrollableList
def tvList2OldTvTextList(tvList:list,oldTvTextList:list):
    oldTvTextList.clear()
    for i in range(len(tvList)):
        if len(tvList[i].get_text())>2: # 为什么原来是>8呢?
            oldTvTextList.append(tvList[i].get_text())
def scrollUntilHasNew(d:u2.Device=None, oldList=None):
    if d is None:
        uu = U2Syner()
        d: u2.Device = uu.deviceList[0]
    while True:
        scrollALittle(d)
        xmlContent = d.dump_hierarchy()
        root = ET.fromstring(xmlContent)
        nodeFansNicknameList = root.findall('.//node[@resource-id="com.xingin.xhs:id/hx_"]')
        if nodeFansNicknameList[-1] not in oldList:
            oldList.clear()
            oldList.extend(nodeFansNicknameList)
            break
def scrollUntilAllNew(d:u2.Device=None, oldList=None):
    if d is None:
        uu = U2Syner()
        d: u2.Device = uu.deviceList[0]
    pass
def recordUserInfo(d:u2.Device=None, userName=None):
    if d is None:
        uu = U2Syner()
        d: u2.Device = uu.deviceList[0]
    userInfoTvList = d().child(textMatches=r'[\d\.万亿 小红书号：a-zA-Z_]+?')
    U = {"用户昵称": userName, "小红书号": None, "链接": None, "点赞数": None, "收藏数": None,
         "评论数": None, "关注数": None, "粉丝数": None, "获赞与收藏数": None, "笔记内容": None, "备注": None}
    isFoundUserId = False
    for k in range(len(userInfoTvList)):
        tmpText = userInfoTvList[k].get_text()
        print("yzprt userInfoTvList[%s]:" % (k), tmpText, userInfoTvList[k].info)
        if tmpText.find("小红书号：") >= 0:
            U["点赞数"], U["收藏数"], U["评论数"], U["小红书号"], U["关注数"], U["粉丝数"], U["获赞与收藏数"] = [
                userInfoTvList[k - 3].get_text(),
                userInfoTvList[k - 2].get_text(),
                userInfoTvList[k - 1].get_text(),
                tmpText,
                userInfoTvList[k + 1].get_text(),
                userInfoTvList[k + 2].get_text(),
                userInfoTvList[k + 3].get_text()
            ]
            isFoundUserId = True
            break
    if not isFoundUserId:
        pass
    if U["用户昵称"] is None:
        xmlContent = d.dump_hierarchy()
        # print("yzprt xmlContent:", xmlContent)
        root = ET.fromstring(xmlContent)
        nodeTvList = root.findall('.//node[@class="android.widget.TextView"]')
        for i in range(len(nodeTvList)):
            # print("yzprt nodeTvList[i]:",i, nodeTvList[i].attrib["text"],(U["小红书号"]))
            if nodeTvList[i].attrib["text"]==(U["小红书号"]):
                U["用户昵称"] = nodeTvList[i-1].attrib["text"]
                print("yzprt U[用户昵称] update:", U["用户昵称"])
                break
    print("yzprt U:", U)
def getCenter(node:ElementTree.Element)->tuple:
    arr = eval(node.attrib['bounds'].replace('][',','))
    return ((arr[0]+arr[2])//2,(arr[1]+arr[3])//2)
def getWidth(node:ElementTree.Element)->int:
    arr = eval(node.attrib['bounds'].replace('][',','))
    # print("yzprt getWidth:", arr[2]-arr[0])
    return arr[2]-arr[0]
def getHeight(node:ElementTree.Element)->int:
    arr = eval(node.attrib['bounds'].replace('][',','))
    return arr[3]-arr[1]
def walkXY_GOODS_LIST_DESC_MODE(d:u2.Device=None):
    if d is None:
        uu = U2Syner()
        d: u2.Device = uu.deviceList[0]
    xmlContent = d.dump_hierarchy()
    print("yzprt xmlContent:", xmlContent)
    root = ET.fromstring(xmlContent)
    nodeList = root.findall('.//')
    nodeGoodsList = []
    print(f'yzprt 11:{11}')
    for i in range(len(nodeList)):
        node = nodeList[i]
        if node.attrib['content-desc'].find("¥") >= 0 or node.attrib['text'].find("¥") >= 0:
            print("yzprt node.attrib:", node.attrib)
            nodeGoodsList.append(node)
    print(f'yzprt 22:{22}',nodeGoodsList)
    while True:
        if len(nodeGoodsList)>0:
            try:
                nodeGoods:ElementTree.Element = nodeGoodsList[0]
                print("yzprt type(nodeGoods):", type(nodeGoods))
                x,y=getCenter(nodeGoods)
                d.click(x,y)
                sleep(2)
                filePath = os.path.join(Config.Params.ROOT_DIR,r"raw/imgs/"+"ScreenShot_"
                                        +TimeUtil.stampS2TimeStr(TimeUtil.getStamp10(),fmt="mdHMS")+".jpg")
                # d.screenshot()
                img = d.screenshot(filePath)
                # img.save(filePath)
                d(description="分享").click()
                sleep(2)
                d(description="复制链接").click()
                sleep(2)
                d.press("back")
                sleep(2)
                d.press("back")
                sleep(2)
            except:
                log.error("yzlog traceback withSqlite:", traceback.format_exc())
            nodeGoodsList.pop(0)
        else:
            pass
def snapNewGoods(goodsTextList:list,mRecyTopY,mRecyBottomY,strictOffsetTop,strictOffsetBottom,d:u2.Device=None):
    xmlContent = d.dump_hierarchy()
    root = ET.fromstring(xmlContent)
    nodeGoodsList = root.findall('.//node[@resource-id="com.taobao.idlefish:id/dx_root"]')
    for i in range(len(nodeGoodsList)):
        nodeGoods = nodeGoodsList[i]
        if isWidthBetweenRatio(d, getWidth(nodeGoods), 0.45, 0.55):
            print("yzprt i, nodeGoods.attrib:", i, nodeGoods.attrib)
            goodsTopY = getNodeBorderPos(nodeGoods, 'top')
            goodsBottomY = getNodeBorderPos(nodeGoods, 'bottom')
            # print(f'yzprt goodsTopY:{goodsTopY}, goodsBottomY:{goodsBottomY}, mRecyTopY:{mRecyTopY}, mRecyBottomY:{mRecyBottomY}')
            if mRecyTopY + strictOffsetTop <= goodsTopY < goodsBottomY <= mRecyBottomY - strictOffsetBottom:
                print("yzprt i, nodeGoods.attrib is intact one ^_^   ^_^   ^_^:", i, nodeGoods.attrib)
                # textList:
                nodeTvList = nodeGoods.findall('.//node[@class="android.widget.TextView"]')
                textList = []
                for k in range(len(nodeTvList)):
                    textList.append(nodeTvList[k].attrib['text'])
                print("yzprt i,textList:", i, textList)
                textListStr = '@n#'.join(textList)
                if textListStr not in goodsTextList:
                    goodsTextList.append(textListStr)
                    # imgList:
                    nodeImgList = nodeGoods.findall('.//node[@class="android.widget.ImageView"]')
                    for k in range(len(nodeImgList)):
                        nodeImg = nodeImgList[k]
                        print("yzprt k:", k, nodeImg.attrib)
                    print(f'yzprt len(goodsTextList):{len(goodsTextList)}, last One:{goodsTextList[-1]}')
                else:
                    print(f'yzprt :{textListStr} already exists')
def walkXY_GOODS_LIST_TEXT_MODE(d:u2.Device=None,isPageTop=False):
    if d is None:
        uu = U2Syner()
        d: u2.Device = uu.deviceList[0]
    xmlContent = d.dump_hierarchy()
    # print("yzprt xmlContent:", xmlContent)
    root = ET.fromstring(xmlContent)
    # nodeRecyclerList = root.findall('.//node[@class="androidx.recyclerview.widget.RecyclerView"]')
    # nodeMainRecycler = getMaxHeightNode(getScrollableNode(nodeRecyclerList))
    # print("yzprt nodeMainRecycler.attrib:", nodeMainRecycler.attrib)
    nodeHomeSecondTab = root.findall('.//node[@resource-id="com.taobao.idlefish:id/rv_home_second_tab"]')[0]
    mRecyTopY = getNodeBorderPos(nodeHomeSecondTab,'bottom')
    print("yzprt nodeHomeSecondTab.bottom:", mRecyTopY)
    nodeIndicatorItems = root.findall('.//node[@resource-id="com.taobao.idlefish:id/indicator_itmes"]')[0]
    mRecyBottomY = getNodeBorderPos(nodeIndicatorItems, 'top')
    print("yzprt nodeIndicatorItems.top:", mRecyBottomY)
    # offsetTopWhenFirst = -2
    strictOffsetTop = 5
    offsetTopWhenPageTop = -2
    strictOffsetBottom = 5
    goodsTextList = []
    # whenPageTop:
    snapNewGoods(goodsTextList,mRecyTopY,mRecyBottomY,offsetTopWhenPageTop,strictOffsetBottom)
    while True:
        snapNewGoods(goodsTextList,mRecyTopY,mRecyBottomY,strictOffsetTop,strictOffsetBottom)
        scrollALittle(d)
    # nodeGoodsList = []
    # for i in range(len(nodeList)):
    #     node = nodeList[i]
    #     if node.attrib['content-desc'].find("¥") >= 0:
    #         print("yzprt node.attrib:", node.attrib)
    #         nodeGoodsList.append(node)
    # while True:
    #     if len(nodeGoodsList)>0:
    #         try:
    #             nodeGoods:ElementTree.Element = nodeGoodsList[0]
    #             print("yzprt type(nodeGoods):", type(nodeGoods))
    #             x,y=getCenter(nodeGoods)
    #             d.click(x,y)
    #             sleep(2)
    #             filePath = os.path.join(Config.Params.ROOT_DIR,r"raw/imgs/"+"ScreenShot_"
    #                                     +TimeUtil.stampS2TimeStr(TimeUtil.getStamp10(),fmt="mdHMS")+".jpg")
    #             # d.screenshot()
    #             img = d.screenshot(filePath)
    #             # img.save(filePath)
    #             d(description="分享").click()
    #             sleep(2)
    #             d(description="复制链接").click()
    #             sleep(2)
    #             d.press("back")
    #             sleep(2)
    #             d.press("back")
    #             sleep(2)
    #         except:
    #             log.error("yzlog traceback withSqlite:", traceback.format_exc())
    #         nodeGoodsList.pop(0)
    #     else:
    #         pass

def walkXHS_FANS_LIST(d:u2.Device=None):
    if d is None:
        uu = U2Syner()
        d: u2.Device = uu.deviceList[0]
    # ll1Fan = d(className="android.widget.LinearLayout",instance=5)
    xmlContent = d.dump_hierarchy()
    print("yzprt xmlContent:", xmlContent)
    root = ET.fromstring(xmlContent)
    nodeFansList = root.findall('.//node[@class="android.widget.LinearLayout"]')
    resIdNickname = ""
    referIndex = 5
    MAX_REPEAT_COUNT = 6
    repeatCount = 0
    for i in range(len(nodeFansList)):
        nodeFan = nodeFansList[i]
        if nodeFan.attrib['index']==str(referIndex):
            print("yzprt nodeFan.attrib:", nodeFan.attrib)
            tvNickname = nodeFan.findall('.//node[@class="android.widget.TextView"]')[0]
            print("yzprt tvNickname.attrib:", tvNickname.attrib)
            resIdNickname = tvNickname.attrib['resource-id']
        # confirm resource-id:
        elif nodeFan.attrib['index']==str(referIndex+1):
            nextIndexNickname=nodeFan.findall('.//node[@class="android.widget.TextView"]')[0].attrib['resource-id']
            if resIdNickname!=nextIndexNickname:
                print("yzprt resIdNickname vs nextIndexNickname:", resIdNickname,'vs',nextIndexNickname)
                raise Exception
            break
    nodeFansNicknameList = root.findall('.//node[@resource-id="com.xingin.xhs:id/hx_"]')
    for i in range(len(nodeFansNicknameList)):
        nodeFanNickName = nodeFansNicknameList[i]
        print("yzprt nodeFanNickname.attrib['text']:",i, nodeFanNickName.attrib['text'])
    # start scroll or end:
    oldNicknameList = nodeFansNicknameList
    while True:
        scrollALittle(d)
        if d(text="发现更多好友").exists:
            print("yzprt 已到达底部: 发现更多好友!")
            break
        xmlContent = d.dump_hierarchy()
        root = ET.fromstring(xmlContent)
        newNodeFansNicknameList = root.findall('.//node[@resource-id="com.xingin.xhs:id/hx_"]')
        try:
            lastNickname = newNodeFansNicknameList[-1].attrib['text']
            if lastNickname not in oldNicknameList:
                print("yzprt a new fan:", lastNickname)
                repeatCount=0
            else:
                repeatCount+=1
                if repeatCount>=MAX_REPEAT_COUNT//2:
                    print("yzprt repeatCount:", repeatCount)
                    if repeatCount>=MAX_REPEAT_COUNT:
                        print("yzprt repeatCount:", repeatCount,"has reached max count!!!!!!")
                        break
            oldNicknameList.pop(0)
            oldNicknameList.append(lastNickname)
        except:
            log.error("yzlog traceback walkXHS_FANS_LIST:", traceback.format_exc())
            print("yzprt repeatCount:", repeatCount,"can not get the node!!!!!!")
            break


def walkXHS_WORKS(d:u2.Device=None):
    if d is None:
        uu = U2Syner()
        d: u2.Device = uu.deviceList[0]
    LIKES_MIN = 10
    d.watcher.when("打开辅助服务").press("back")
    d.watcher.when("立即安装").press("back")
    d.watcher.when("去使用").call(lambda d:myPress(d,"press",2))
    d.watcher.when("关注并退出").call("退出")
    d.watcher.when("打开通知，发现更多感兴趣的笔记").press("back")
    d.watcher.when("确认不再关注").press("确认")
    d.watcher.start()
    d.app_start(pkgNameXHS,wait=True)
    appInfo = d.app_current()
    # d.dump_hierarchy()

    # userInfoTvList = d().child(textMatches=r'[关注粉丝获赞与收藏]+?')
    # userInfoTvList = d().child(textMatches=r'[\d\.万 小红书号：a-zA-Z]+?')
    # for k in range(len(userInfoTvList)):
    #     print("yzprt2 userInfoTvList[%s]:" % (k), userInfoTvList[k].get_text())

    oldTvTextList = []

    while True:
        recyclerView = getMaxHeightUio(d(className="androidx.recyclerview.widget.RecyclerView"))
        # recyclerView = d(className="androidx.recyclerview.widget.RecyclerView")[-1]
        # print("yzprt recyclerView.info:", recyclerView.info)
        # print("yzprt recyclerView.childCount:", recyclerView.info["childCount"])

        # tvLikesCountList = recyclerView.child(textMatches=r"[\d万]+")
        # print("yzprt len(tvLikesCountList):", len(tvLikesCountList))
        # for i in range(len(tvLikesCountList)):
        #     ele = tvLikesCountList[i]
        #     print("yzprt ele likeCounts:", ele.get_text())

        # tvList = recyclerView.child(textMatches=r"[\u4e00-\u9fa5_a-zA-Z0-9]+")
        tvList = recyclerView.child(textMatches=r'[^"]+?')
        if not isNewTvTextList(tvList, oldTvTextList):
            scrollALittle(d)
            continue
        else:
            oldTvTextList.clear()
        print("yzprt len(tvList):", len(tvList))
        for i in range(len(tvList)):
            try:
                ele = tvList[i]
                text: str = ele.get_text()
                print("yzprt text:", text)
                if text not in ["推荐", "视频", "直播", "头像", "美食", "壁纸", "穿搭"]: #  , "综合", "复盘笔记", '干货知识', '入门基础知识', '持仓图'
                    # oldTvTextList.append(text)
                    pass
                # else:
                #     break
                if len(text) < 10:
                    if text.endswith("万"):
                        try:
                            likesCount = float(text.replace("万", "")) * 10000
                        except:
                            print("yzprt likesCount convert error1:", text)
                            # likesCount = 9999999901
                            continue
                    else:
                        try:
                            likesCount = int(text)
                            likesCount = float(likesCount)
                        except:
                            print("yzprt likesCount convert error2:", text)
                            # likesCount = 9999999902
                            continue
                    if likesCount >= LIKES_MIN:
                        tvUserName = tvList[i - 1]
                        if re.search(r"^[\d-]+$", tvUserName.get_text()) or re.search(r"\d+[天时]前",tvUserName.get_text()):
                            tvUserName = tvList[i - 2]
                        userName = tvUserName.get_text()
                        print("yzprt got one >3万:", userName)
                        # continue
                        tvUserName.click()
                        sleep(2)
                        if d(text='更多直播').exists:
                            print(f'yzprt is 直播...')
                            d.press("back")
                            sleep(1)
                            while not d(text="首页").exists:
                                print(f'yzprt is still at 直播...')
                                sleep(1)
                                d.press("back")
                            continue
                        d(text=userName).click()
                        sleep(1)
                        userInfoTvList = d().child(textMatches=r'[\d\.万 小红书号：a-zA-Z_]+?')
                        U = {"用户昵称": userName, "小红书号": None, "链接": None, "点赞数": None, "收藏数": None,
                             "评论数": None, "关注数": None, "粉丝数": None, "获赞与收藏数": None, "笔记内容": None, "备注":None}
                        isFoundUserId = False
                        for k in range(len(userInfoTvList)):
                            tmpText = userInfoTvList[k].get_text()
                            print("yzprt userInfoTvList[%s]:" % (k), tmpText, userInfoTvList[k].info)
                            if tmpText.find("小红书号：") >= 0:
                                U["点赞数"], U["收藏数"], U["评论数"], U["小红书号"], U["关注数"], U["粉丝数"], U["获赞与收藏数"] = [
                                    userInfoTvList[k - 3].get_text(),
                                    userInfoTvList[k - 2].get_text(),
                                    userInfoTvList[k - 1].get_text(),
                                    tmpText,
                                    userInfoTvList[k + 1].get_text(),
                                    userInfoTvList[k + 2].get_text(),
                                    userInfoTvList[k + 3].get_text()
                                ]
                                isFoundUserId = True
                                break
                        if not isFoundUserId:
                            pass
                        # isFansAccessible:
                        isFansAccessible = False
                        d(text=userInfoTvList[k + 2].get_text()).click()
                        sleep(2)
                        if d(text="查看全部").exists:
                            isFansAccessible = True
                            U["备注"] = "粉丝可见;"
                            d.press("back")
                        else:
                            U["备注"] = "粉丝不可见;"
                        d.press("back")
                        sleep(1)
                        while True:
                            if d(resourceId="com.xingin.xhs:id/shareButton").exists:
                                d(resourceId="com.xingin.xhs:id/shareButton").click()
                                break
                            elif d(resourceId="com.xingin.xhs:id/moreOperateIV").exists:
                                d(resourceId="com.xingin.xhs:id/moreOperateIV").click()
                                break
                            print(f'yzprt sleep(0.5):')
                            sleep(0.5)
                        # d.click(0.924, 0.082)
                        d(text="复制链接").wait(timeout=5.0)
                        d(text="复制链接").click()
                        d.app_start(pkgNameTool, wait=True)
                        # d.set_clipboard(TimeUtil.getFormatTimeNow())
                        d(text="测试按钮").click()
                        link = d(resourceId="com.codeboy.qianghongbao:id/et_msg").get_text()
                        U["链接"] = link
                        d.app_start(appInfo["package"], wait=True)
                        d(resourceId="com.xingin.xhs:id/noteContentText").wait(timeout=5)
                        if d(resourceId="com.xingin.xhs:id/noteContentText").exists:
                            noteContentText = d(resourceId="com.xingin.xhs:id/noteContentText").get_text()
                        else:
                            print("yzprt noteContentText not exitsts!!!!!")
                            noteList = d().child(textMatches=r'[^"]+?')
                            noteArr = []
                            for x in range(len(noteList)):
                                xtext = noteList[x].get_text()
                                if len(xtext) > 10:
                                    noteArr.append(xtext)
                            noteContentText = '\n'.join(noteArr)
                        U["笔记内容"] = noteContentText
                        try:
                            with open(os.path.join(os.path.join(Config.Params.ROOT_DIR,"./raw/records"), f"xhs_baokuan_{d.serial}.txt"), 'a', encoding='utf-8',
                                      errors='ignore') as f:
                                f.write("\n%s" % ('\t'.join(
                                    [U["用户昵称"],
                                     U["小红书号"].replace("小红书号：", ""),
                                     # U["链接"][U["链接"].index("http://"):U["链接"].index("，复制本条信息")],
                                     U["链接"],
                                     U["点赞数"].replace(" ", ""),
                                     U["收藏数"].replace(" ", ""),
                                     U["评论数"].replace(" ", ""),
                                     U["关注数"].replace(" ", ""),
                                     U["粉丝数"].replace(" ", ""),
                                     U["获赞与收藏数"].replace(" ", ""),
                                     U["笔记内容"].replace("\n", "@n#").replace("\t", "@t#"),
                                     U["备注"].replace(" ", ""),
                                     TimeUtil.getFormatTimeNow()]
                                )))
                        except:
                            with open(os.path.join(os.path.join(Config.Params.ROOT_DIR,"./raw/records"), f"xhs_baokuan_{d.serial}.txt"), 'a', encoding='utf-8',
                                      errors='ignore') as f:
                                f.write("\n%s" % ('\t'.join(
                                    [U["用户昵称"], U["链接"], U["笔记内容"].replace("\n", "@n#"), "dataAbnormal",TimeUtil.getFormatTimeNow()])))
                        print("yzprt U:", U)
                        xhsLikeCollConcAfBack(d, U, (0, 500000), (0, 500000), (0, 500000))
                        # oldTvTextList.clear()
                        # print("yzprt oldTvTextList:", oldTvTextList)
                        d.press("back")
                        sleep(1)
            except:
                # oldTvTextList.clear()
                # oldTvTextList.append(U["用户昵称"])
                # oldTvTextList.append(U["笔记内容"])
                log.info("yzlog traceback TryExcept:", i, traceback.format_exc())
        print("yzprt oldTvTextList bf:", oldTvTextList)
        tvList2OldTvTextList(tvList,oldTvTextList)
        print("yzprt oldTvTextList af:", oldTvTextList)
    d.watcher.stop()
    d.watcher.remove()

def checkAndRestartDeviceList(deviceList,func,params=None):
    for i in range(len(deviceList)):
        d: u2.Device = deviceList[i]
        threadName = "%s_%s" % (func.__name__, d.serial)
        isA,isB,isC=True,True,True
        isA = (threadName not in threadDict)
        if not isA:
            isB = (threadDict[threadName] is None)
            isC = (not threadDict[threadName].isAlive())
        print(f'yzprt isA:{isA}, isB:{isB}, isC:{isC}')
        if isA or isB or isC:
            threadDict[threadName] = Thread(target=func, args=(d,), name="t-%s" % (d.serial))
            threadDict[threadName].start()
            log.info(f'yzlog restarted threadName:{threadName}')
            sleep(1)
def mWalkThreadOfFunc(func,params=None):
    print(f'yzprt func.__name__:{func.__name__}')
    u2 = U2Syner()
    u2.mSetWatcher()
    checkAndRestartDeviceList(u2.deviceList,func,params=params)
    while True:
        checkAndRestartDeviceList(u2.deviceList,func,params=params)
        sleep(10)

def isWidthBetweenRatio(d:u2.Device,width,ratio1,ratio2):
    if ratio1 <= width/d.window_size()[0] <= ratio2:
        return True
    else:
        return False
def isHeightBetweenRatio(d:u2.Device,height,ratio1,ratio2):
    if ratio1 <= height/d.window_size()[1] <= ratio2:
        return True
    else:
        return False
def getNodeBorderPos(node:ElementTree.Element,direction=None):
    arr = eval(node.attrib['bounds'].replace('][', ','))
    if direction=='left':
        return arr[0]
    elif direction=='top':
        return arr[1]
    elif direction=='right':
        return arr[2]
    elif direction=='bottom':
        return arr[3]
    else:
        return -1
def getLinkList(d:u2.Device):
    reflectDict = {"45caac46":"d290aa9a","d290aa9a":"249cc885","249cc885":"68c5aa3e","68c5aa3e":"45caac46","9ec7c44f":"45caac46",}
    targetDeviceStr = reflectDict[d.serial]
    filePath = r"D:\PythonProjects\adb-multi\raw\records\xhs_baokuan_%s.txt"%(targetDeviceStr)
    log.info("yzlog filePath:", filePath)
    rawStr = IOUtil.file2Str(filePath)
    linkList = re.findall(r"[^\t]+打开【小红书】App查看精彩内容！\t",rawStr)
    return linkList
if __name__ == '__main__':
    d = u2.connect(deviceSerial)
    log.info("yzlog 当前设备序列号:", deviceSerial)
    pass
    # mWalkThreadOfFunc(func=walkXQ)
    # mWalkThreadOfFunc(func=walkXHS_WORKS)
    # walkZSXQ()
    # walkXHS_WORKS(d)
    # walkXHS_FANS_LIST()
    # recordUserInfo()
    walkXHS_COMMENTS(d)
    # walkXQ()
    # testSth()
    pass
    # d = u2.connect(deviceSerial)
    # print("yzprt d.serial:", d.serial)
    # print("yzprt d.device_info:", d.device_info)
    # print("yzprt d.window_size:", d.window_size())
    # walkXY_GOODS_LIST_TEXT_MODE(d=d)
